#include "HY1C_out.h"
/* ============================================================================ */
/* module l1_hmodis_hdf.c - functions to read MODIS HIRES L1B for MSL12         */
/*                                                                              */
/* Written By:  B. Franz, NASA/SIMBIOS, January 2003.                           */
/* Modified By: J. Gales, NASA/OBPG,    August 2005.                            */
/* Conversion for 16-band MODIS: B. Franz, J. Gales, 2006.                      */
/*                                                                              */
/* ============================================================================ */

#include "l1_hmodis_hdf.h"
#include "l1_modis_hdf.h"
#include "l12_proto.h"
#include "hdf_utils.h"
#include "alloc_2d.h"

#define EOSMETALEN 32768

#define MAXBANDS (NBANDS+NBANDSIR+1)
#define NDET     40

static int have_extract = 0;

static int32 sd_id[3] = {-1};
static int32 sd_id_g;
static int32 spix   = 0;
static int32 sscan  = 0;  /* start scan in original granule */
static int32 rscan  = 0;  /* start scan in extract granule  */
static int32 resolution = 1000;
static int32 ndet = 10;

static int32 np1000 = 1354;
static int32 sp1000 = 0;
static int32 np500  = 2708;
static int32 sp500  = 0;
static int32 np250  = 5416;
static int32 sp250  = 0;

static int32 nd1000 = 10;
static int32 nd500  = 20;
static int32 nd250  = 40;

static float32 **lon1000  = NULL;
static float32 **lat1000  = NULL;
static float32 **hgt1000  = NULL;
static float32 **solz1000 = NULL;
static float32 **sola1000 = NULL;
static float32 **senz1000 = NULL;
static float32 **sena1000 = NULL;
static float32 **fdatabuf[MAXBANDS];

static int destripe = 0;

/* RSMAS corrections to Terra IR radiances (20,22,23,27,28,29,31,32) */
static float radoff[NBANDSIR][NDET] = {
{-0.000972, 0.014200, 0.000022, 0.000238,-0.000003, 0.003760, 0.002337, 0.000084, 0.008848, 0.005050},
{-0.002300, 0.000600, 0.000236,-0.000280,-0.000003, 0.002798, 0.003496, 0.018035, 0.002942, 0.001787},
{-0.003833, 0.003657, 0.002118, 0.000798,-0.000003, 0.000208, 0.000399, 0.000553, 0.000258, 0.021128},
{0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0},
{0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0},
{0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0},
{-0.000423,-0.000242,-0.000330,-0.000065,-0.000001,-0.000006, 0.000064, 0.000398, 0.000362, 0.000322},
{-0.000433,-0.000246,-0.000222,-0.000148,-0.000001, 0.000068, 0.000221, 0.000221, 0.000437, 0.000303}
};
static float mfact[NBANDSIR] = {0.0,0.0,0.0005,0.0,0.0,0.0,0.0028,0.00278};

/* RSMAS AQUA modis corrections for some bands and detectors */
static float ch20d2cor  =  0.996666;    /* channel 20 detector 2  */
static float ch20d3cor  =  1.0044444;   /* channel 20 detector 3  */
static float ch20d10cor =  1.0033333;   /* channel 20 detector 10 */
static float ch22d1cor  =  1.0030075;   /* channel 22 detector 1  */
static float ch22d8cor  =  1.0007518;   /* channel 22 detector 8  */
static float ch22d9cor  =  1.0015037;   /* channel 22 detector 9  */
static float ch22d10cor =  1.0022556;   /* channel 22 detector 10 */
static float ch23d1cor  =  1.0192857;   /* channel 23 detector 1  */


/* ----------------------------------------------------------------------------------- */
/* modis_data_interp() - interpolates from 1km counts to 250 or 500m pixels.           */
/*                                                                                     */
/* ipixl = full resolution pixel (frame) number, from zero                             */
/* iline = full resolution line (detector) number, from zero                           */
/*                                                                                     */
/* B. Franz, SAIC, January 2006 .                                                      */
/* ----------------------------------------------------------------------------------- */
void modis_data_interp(int band, int32_t ipixl2, int32_t iline2, int res1, int res2, float32 *data)
{
    int32_t   ipixl;
    int32_t   iline;
    float  fpixl;
    float  fline;
    float  dpixl;
    float  dline;
    int    nline;
    int    npixl;
    float  val[4];
    float  sumv;
    int    cntv;
    uint16 maxv;
    int    i;

    /* note: this function presumes that ipixl2=0 is at the center of a 1km pixel, */
    /* as it will always be for files generated via MODl1extract L1A               */

    switch (res1+res2) {
      case 1500: /* 1000 to 500 */
	nline = nd1000;
	npixl = np1000;
	fpixl = 0.50*ipixl2;
	fline = 0.50*iline2 - 0.25;
	break;
      case 1250: /* 1000 to 250 */
	nline = nd1000;
	npixl = np1000;
	fpixl = 0.25*ipixl2;
	fline = 0.25*iline2 - 0.375;
	break;
      case 750: /* 500 to 250 */
	nline = nd500;
	npixl = np500;
	fpixl = 0.50*ipixl2;
	fline = 0.50*iline2 - 0.25;
	break;
      default:
	HY1C_out("%s Line %d: Unknown resolution change, %d to %d\n",__FILE__,__LINE__,res1,res2);
	exit(1);
    }

    /* index and weighting into input data block */
    iline = MIN(MAX((int)floor((float)fline),0),nline-2);
    dline = (float)fline - (float)iline;
    ipixl = MIN(MAX((int)floor((float)fpixl),0),npixl-2);
    dpixl = (float)fpixl - (float)ipixl;

    /* interpolation: account for flagged values */

    val[0] = fdatabuf[band][iline+0][ipixl+0];
    val[1] = fdatabuf[band][iline+0][ipixl+1];
    val[2] = fdatabuf[band][iline+1][ipixl+0];
    val[3] = fdatabuf[band][iline+1][ipixl+1];

    sumv = 0.0;
    cntv = 0;
    maxv = 0;

    for( i = 0; i < 4; i++ ) {
	if (val[i] <= 65500) {
	    sumv = sumv + val[i];
	    cntv++;
	}
	if( val[i] > maxv )
	    maxv = val[i];
    }

    /* If we have four non-flagged samples, we bilinearly interpolate.  If we */
    /* have 0-3 samples, just set to the max flag value (or use average)      */

    switch (cntv) {
      case 4:
	*data = ( (1.0-dline)*(val[0]*(1.0-dpixl) + val[1]*dpixl) +
			dline*(val[2]*(1.0-dpixl) + val[3]*dpixl) );
	break;
      case 0:
	*data = maxv;
	break;
      default:
	//*data = maxv;
	*data = sumv/cntv;   // re-enabled this; don't know why it was disabled
	break;
    }
}


/* ----------------------------------------------------------------------------------- */
/* modis_geo_interp() - interpolates from 1km geolocation to 250 or 500m pixels.       */
/*                                                                                     */
/* ipixl = full resolution pixel (frame) number, from zero                             */
/* iline = full resolution line (detector) number, from zero                           */
/*                                                                                     */
/* B. Franz, SAIC, January 2006 .                                                      */
/* ----------------------------------------------------------------------------------- */
void modis_geo_interp(int32_t ipixl2, int32_t iline2, int resolution,
		      float *lon,  float *lat,  float *hgt,
		      float *solz, float *sola,
		      float *senz, float *sena, int lonlat)
{
    float  fpixl;
    float  fline;
    double dpixl;
    double dline;
    int32_t   ipixl;
    int32_t   iline;
    double min_val;
    double max_val;
    double val[4];
    int    ival;

    /* note: this function presumes that ipixl2=0 is at the center of a 1km pixel, */
    /* as it will always be for files generated via MODl1extract L1A               */

    switch (resolution) {
      case 250:
	fpixl = 0.25*ipixl2;
	fline = 0.25*iline2 - 0.375;
	break;
      case 500:
	fpixl = 0.50*ipixl2;
	fline = 0.50*iline2 - 0.25;
	break;
      default:
	HY1C_out("%s Line %d: Unknown resolution = %d\n",__FILE__,__LINE__,resolution);
	exit(1);
    }

    /* index and weighting into 1km geolocation block */
    iline = MIN(MAX((int)floor((double)fline),0),nd1000-2);
    dline = (double)fline - (double)iline;
    ipixl = MIN(MAX((int)floor((double)fpixl),0),np1000-2);
    dpixl = (double)fpixl - (double)ipixl;

    /* longitude interpolation: account for dateline */

    val[0] = (double)lon1000[iline+0][ipixl+0];
    val[1] = (double)lon1000[iline+0][ipixl+1];
    val[2] = (double)lon1000[iline+1][ipixl+0];
    val[3] = (double)lon1000[iline+1][ipixl+1];

    min_val = max_val = val[0];

    for( ival = 1; ival < 4; ival++ ) {
	if( val[ival] < min_val )
	    min_val = val[ival];
	else if( val[ival] > max_val )
	    max_val = val[ival];
    }

    if( max_val > 180.0 + min_val ) {
	for( ival = 0; ival < 4; ival++ ) {
	   if( val[ival] < 0.0 )
	      val[ival] += 360.0;
	}
    }

    *lon = ((1.0-dline)*(val[0]*(1.0-dpixl) + val[1]*dpixl) +
		  dline*(val[2]*(1.0-dpixl) + val[3]*dpixl));

    if( *lon >= 180.0 )
	 *lon = *lon-360.0;


    /* latitude interpolation */

    val[0] = (double)lat1000[iline+0][ipixl+0];
    val[1] = (double)lat1000[iline+0][ipixl+1];
    val[2] = (double)lat1000[iline+1][ipixl+0];
    val[3] = (double)lat1000[iline+1][ipixl+1];

    *lat = ((1.0-dline)*(val[0]*(1.0-dpixl) + val[1]*dpixl) +
		  dline*(val[2]*(1.0-dpixl) + val[3]*dpixl));

    if(lonlat)
	return;

    /* height interpolation */

    val[0] = (double)hgt1000[iline+0][ipixl+0];
    val[1] = (double)hgt1000[iline+0][ipixl+1];
    val[2] = (double)hgt1000[iline+1][ipixl+0];
    val[3] = (double)hgt1000[iline+1][ipixl+1];

    *hgt = ((1.0-dline)*(val[0]*(1.0-dpixl) + val[1]*dpixl) +
		  dline*(val[2]*(1.0-dpixl) + val[3]*dpixl));


    /* solar zenith interpolation */

    val[0] = (double)solz1000[iline+0][ipixl+0];
    val[1] = (double)solz1000[iline+0][ipixl+1];
    val[2] = (double)solz1000[iline+1][ipixl+0];
    val[3] = (double)solz1000[iline+1][ipixl+1];

    *solz = ((1.0-dline)*(val[0]*(1.0-dpixl) + val[1]*dpixl) +
		  dline*(val[2]*(1.0-dpixl) + val[3]*dpixl));


    /* solar azimuth interpolation */

    val[0] = (double)sola1000[iline+0][ipixl+0];
    val[1] = (double)sola1000[iline+0][ipixl+1];
    val[2] = (double)sola1000[iline+1][ipixl+0];
    val[3] = (double)sola1000[iline+1][ipixl+1];

    *sola = ((1.0-dline)*(val[0]*(1.0-dpixl) + val[1]*dpixl) +
		   dline*(val[2]*(1.0-dpixl) + val[3]*dpixl));


    /* sensor zenith interpolation */

    val[0] = (double)senz1000[iline+0][ipixl+0];
    val[1] = (double)senz1000[iline+0][ipixl+1];
    val[2] = (double)senz1000[iline+1][ipixl+0];
    val[3] = (double)senz1000[iline+1][ipixl+1];

    *senz = ((1.0-dline)*(val[0]*(1.0-dpixl) + val[1]*dpixl) +
		   dline*(val[2]*(1.0-dpixl) + val[3]*dpixl));


    /* sensor azimuth interpolation, handle singularity */

    val[0] = (double)sena1000[iline+0][ipixl+0];
    val[1] = (double)sena1000[iline+0][ipixl+1];
    val[2] = (double)sena1000[iline+1][ipixl+0];
    val[3] = (double)sena1000[iline+1][ipixl+1];

    if (*senz < 0.05)
	*sena = 0.0;
    else
	*sena = ((1.0-dline)*(val[0]*(1.0-dpixl) + val[1]*dpixl) +
		       dline*(val[2]*(1.0-dpixl) + val[3]*dpixl));
}


/* ----------------------------------------------------------------------------------- */
/* subframe_calibration() - loads subframe calibration factors and applies.            */
/*                                                                                     */
/* B. Franz, SAIC, February 2003.                                                      */
/* ----------------------------------------------------------------------------------- */
void subframe_calibration(int32_t sensorID, int32_t ib, float mrad, float brad,
				    int32_t spix, int32_t npix, float32 data[])
{
#define NSFWAVE 7
#define MAXSF   4
#define MAXRAD  100

    static int   firstCall = 1;
    static float sftable[NSFWAVE][1+MAXSF][MAXRAD];
    static int   twave  [NSFWAVE] = {469,555,645,859,1240,1640,2130};
    static int   nsfsub [NSFWAVE] = {2,2,4,4,2,2,2};
    static int   nsfrad [NSFWAVE];
    static int32_t  iband  [NSFWAVE];

    float rad, sfcor;
    int32_t irad, ip, iw, ipb, isf;

    if (firstCall) {
	char *tmp_str;
	char  line   [81];
	char  path   [FILENAME_MAX] = "";
	char  file   [FILENAME_MAX] = "";
	FILE *fp = NULL;

	if ((tmp_str = getenv("OCDATAROOT")) == NULL) {
	    HY1C_out("OCDATAROOT environment variable is not defined.\n");
	    exit(1);
	}

	strcpy(path,tmp_str); strcat(path,"/"); strcat(path,sensorDir[sensorID]); strcat(path,"/cal/");

	for (iw=0; iw<NSFWAVE; iw++) {
	    iband[iw] = bindex_get(twave[iw]);
	    sprintf(file,"%s%s%s%s%3d%s",path,"subframecor_",sensorDir[sensorID],"_",twave[iw],".dat");
            if(want_verbose)
                HY1C_out("\nLoading subframe correction table from %s",file);
	    if ( (fp = fopen(file,"r")) == NULL ) {
		fHY1C_out(stderr,
		     "-E- %s line %d: unable to open %s for reading\n",__FILE__,__LINE__,file);
		exit(1);
	    }

	    while ( fgets( line, 80, fp ) ) {
		if ( strncmp(line,"/end_header",11) == 0 )
		    break;
	    }

	    irad = 0;
	    while ( fgets( line, 80, fp ) ) {
		if (nsfsub[iw] == 2)
		    sscanf(line,"%f %f %f",&sftable[iw][0][irad],
			&sftable[iw][1][irad],&sftable[iw][2][irad]);
		else
		    sscanf(line,"%f %f %f %f %f",&sftable[iw][0][irad],
			&sftable[iw][1][irad],&sftable[iw][2][irad],&sftable[iw][3][irad],&sftable[iw][4][irad]);
		irad++;
		if (irad == MAXRAD) {
		    fHY1C_out(stderr,
			 "-E- %s line %d: subframe correction table exceeded allocation.\n",
			 __FILE__,__LINE__);
		    exit(1);
		}
	    }
	    nsfrad[iw] = irad;
	    fclose(fp);
	}

        if(want_verbose)
            HY1C_out("\nSubframe destriping corrections enabled.\n\n");

	firstCall = 0;
    }


    for (iw=0; iw<NSFWAVE; iw++)
	if (ib == iband[iw])
	    break;
    if (iw == NSFWAVE) {
	fHY1C_out(stderr,"-E- %s line %d: attempt to correct non-subframed band %d.\n",__FILE__,__LINE__,ib);
	return;
    }

    for (ip=0; ip<npix; ip++) {
	if (data[ip] < 65000) {
	    rad = (data[ip] - brad)*mrad;
	    isf = (ip + spix) % nsfsub[iw];
	    for (irad=0; irad<nsfrad[iw]-1; irad++) {
		if (rad < sftable[iw][0][irad]) break;
	    }
	    if (irad == 0 || irad == (nsfrad[iw]-1))
		sfcor = sftable[iw][isf+1][irad];
	    else {
		sfcor = sftable[iw][isf+1][irad-1]
		      + (rad - sftable[iw][0][irad-1])
		      * (sftable[iw][isf+1][irad]-sftable[iw][isf+1][irad-1]) /
			(sftable[iw][0][irad]-sftable[iw][0][irad-1]);
	    }
	    data[ip] /= sfcor;
	}
    }
}



/* ----------------------------------------------------------------------------------- */
/* openl1_hmodis_hdf() - opens a MODIS L1B file for reading.                           */
/*                                                                                     */
/* B. Franz, SAIC, February 2003.                                                      */
/* ----------------------------------------------------------------------------------- */
int openl1_hmodis_hdf(filehandle *file)
{
    int32  npix;
    int32  nscan;

    int32  sds_id;
    int32  rank;
    int32  dims[3];
    int32  type;
    int32  numattr;

    int32  itemp;
    uint32 gflags[8];
    char   cdata[32];
    char   namebuf [FILENAME_MAX];
    char   name250 [FILENAME_MAX];
    char   name500 [FILENAME_MAX];
    char   name1000[FILENAME_MAX];
    char   dirbuf  [FILENAME_MAX];
    char   temp    [FILENAME_MAX];
    char   *p = NULL;
    int convention = 0;

    memset(namebuf, '\0',FILENAME_MAX);
    memset(name250, '\0',FILENAME_MAX);
    memset(name500, '\0',FILENAME_MAX);
    memset(name1000,'\0',FILENAME_MAX);

    strcpy(temp,    file->name);
    strcpy(dirbuf,  dirname(temp));
    strcat(dirbuf,  "/");
    strcpy(temp,    file->name);
    strcpy(namebuf, basename(temp));

    if ((p = strstr(namebuf,"QKM")) != NULL) {
	if (file->input->resolution == -1)
	    file->input->resolution = 250;
    } else if ((p = strstr(namebuf,"HKM")) != NULL) {
	if (file->input->resolution == -1)
	    file->input->resolution = 500;
    } else if ((p = strstr(namebuf,"1KM")) != NULL) {
	if (file->input->resolution == -1)
	    file->input->resolution = 1000;
	convention = 1;
    } else if ((p = strstr(namebuf,"LAC")) != NULL) {
	if (file->input->resolution == -1)
	    file->input->resolution = 1000;
	convention = 2;
    } else {
	p = namebuf+strlen(namebuf);
	if (file->input->resolution == -1)
	    file->input->resolution = 1000;
	convention = 3;
    }

    strcpy (name250, dirbuf);
    strncat(name250, namebuf,p-namebuf);
    strcpy (name500, dirbuf);
    strncat(name500, namebuf,p-namebuf);
    strcpy (name1000,dirbuf);
    strncat(name1000,namebuf,p-namebuf);

    /* Capture processing resolution */
    resolution = file->input->resolution;
    if(want_verbose)
        HY1C_out("Processing at %d meter resolution.\n",resolution);

    /* If not following std naming conventions, assume a 1km file */
    if (p == NULL) {
	sd_id[2] = SDstart(file->name, DFACC_RDONLY);
	if(sd_id[2] == FAIL){
	    fHY1C_out(stderr,"-E- %s line %d: SDstart(%s, %d) failed.\n",
	    __FILE__,__LINE__,file->name,DFACC_RDONLY);
	    return(HDF_FUNCTION_ERROR);
	}
        if(want_verbose)
            HY1C_out("    1000-meter file: %s\n",file->name);

    } else {

	if (resolution < 500) {
	    if (convention != 3) {
		strcat(name250,"QKM");
		strcat(name250,p+3);
	    } else {
		strcat(name250,"_QKM");
	    }
            if(want_verbose)
                HY1C_out("     250-meter file: %s\n",name250);
	    sd_id[0] = SDstart(name250, DFACC_RDONLY);
	    if(sd_id[0] == FAIL){
		fHY1C_out(stderr,"-E- %s line %d: SDstart(%s, %d) failed.\n",
		__FILE__,__LINE__,name250,DFACC_RDONLY);
		return(HDF_FUNCTION_ERROR);
	    }
	}

	if (resolution < 1000) {
	    if (convention != 3) {
		strcat(name500,"HKM");
		strcat(name500,p+3);
	    } else {
		strcat(name500,"_HKM");
	    }
            if(want_verbose)
                HY1C_out("     500-meter file: %s\n",name500);
	    sd_id[1] = SDstart(name500, DFACC_RDONLY);
	    if(sd_id[1] == FAIL){
		fHY1C_out(stderr,"-E- %s line %d: SDstart(%s, %d) failed.\n",
		__FILE__,__LINE__,name500,DFACC_RDONLY);
		return(HDF_FUNCTION_ERROR);
	    }
	}

	switch (convention) {
	  case 1:
	    strcat(name1000,"1KM");
	    strcat(name1000,p+3);
	    break;
	  case 2:
	    strcat(name1000,"LAC");
	    strcat(name1000,p+3);
	    break;
	  case 3:
	    break;
	  default:
	    strcat(name1000,"1KM");
	    strcat(name1000,p+3);
	    sd_id[2] = SDstart(name1000, DFACC_RDONLY);
	    if(sd_id[2] == FAIL) {
	      memset(name1000,'\0',FILENAME_MAX);
	      memcpy(name1000,namebuf,p-namebuf);
	      strcat(name1000,"LAC");
	      strcat(name1000,p+3);
	    }
	    break;
	}
        if(want_verbose)
            HY1C_out("    1000-meter file: %s\n",name1000);
	sd_id[2] = SDstart(name1000, DFACC_RDONLY);
	if(sd_id[2] == FAIL){
//	    fHY1C_out(stderr,"-E- %s line %d: SDstart(%s, %d) failed.\n",
//	    __FILE__,__LINE__,name1000,DFACC_RDONLY);
//	    return(HDF_FUNCTION_ERROR);
	}

	/* Make sure this is not an ocean-band sub-setted L1 file */
	if (getHDFattr(sd_id[2],"Rescaled Ocean R","EV_250_Aggr1km_RefSB",(VOIDP)&itemp) == 0) {
	    HY1C_out("\nThis L1B file appears to have been derived from an ocean-band subsetted L1A file,\n");
	    HY1C_out("so it does not contain any data from the MODIS Land/Cloud bands, at any resolution.\n");
	    HY1C_out("Set resolution=-1 for standard ocean processing.\n");
	    exit(1);
	}
    }
    if(want_verbose)
        HY1C_out("\n");


    /* Get pixel and scan dimensions */
    switch (resolution) {
      case 250:
	sds_id = SDselect(sd_id[0],SDnametoindex(sd_id[0],("EV_250_RefSB")));
	if (SDgetinfo(sds_id,NULL,&rank,dims,&type,&numattr) == -1) {
	    fHY1C_out(stderr,"-E- %s line %d: error getting dimension info.\n",
	    __FILE__,__LINE__);
	    return(HDF_FUNCTION_ERROR);
	}
	npix   = dims[2];
	nscan  = dims[1];
	if (getHDFattr(sd_id[0],"Extract Pixel Count","",(VOIDP)&itemp) == 0 && itemp > 0) {
	    npix  = itemp*4;
	    getHDFattr(sd_id[0],"Extract Pixel Offset","",(VOIDP)&itemp);
	    spix  = itemp*4;
	    getHDFattr(sd_id[0],"Extract Line Offset","",(VOIDP)&itemp);
	    sscan = itemp*nd250;
	    have_extract = 1;
            if(want_verbose) {
                HY1C_out("File was generated from L1A extract of size %d x %d\n",npix,nscan);
                HY1C_out("  Pixels %d - %d\n",spix+1,spix+npix);
                HY1C_out("  Lines  %d - %d\n",sscan+1,sscan+nscan);
            } // want_verbose
        }
	ndet   = nd250;
	np1000 = npix/4;
	sp1000 = spix/4;
	np500  = npix/2;
	sp500  = spix/2;
	get_modis_calfile(sd_id[0],file->calfile); /* read list of inputs to L1B */
	break;
      case 500:
	sds_id = SDselect(sd_id[1],SDnametoindex(sd_id[1],("EV_500_RefSB")));
	if (SDgetinfo(sds_id,NULL,&rank,dims,&type,&numattr) == -1) {
	    fHY1C_out(stderr,"-E- %s line %d: error getting dimension info.\n",
	    __FILE__,__LINE__);
	    return(HDF_FUNCTION_ERROR);
	}
	npix   = dims[2];
	nscan  = dims[1];
	if (getHDFattr(sd_id[1],"Extract Pixel Count","",(VOIDP)&itemp) == 0 && itemp > 0) {
	    npix  = itemp*2;
	    getHDFattr(sd_id[1],"Extract Pixel Offset","",(VOIDP)&itemp);
	    spix  = itemp*2;
	    getHDFattr(sd_id[1],"Extract Line Offset","",(VOIDP)&itemp);
	    sscan = itemp*nd500;
	    have_extract = 1;
            if(want_verbose) {
                HY1C_out("File was generated from L1A extract of size %d x %d\n",npix,nscan);
                HY1C_out("  Pixels %d - %d\n",spix+1,spix+npix);
                HY1C_out("  Lines  %d - %d\n",sscan+1,sscan+nscan);
            } // want_verbose
        }
	ndet   = nd500;
	np1000 = npix/2;
	sp1000 = spix/2;
	np500  = npix;
	sp500  = spix;
	get_modis_calfile(sd_id[1],file->calfile); /* read list of inputs to L1B */
	break;
      default:
	sds_id = SDselect(sd_id[2],SDnametoindex(sd_id[2],("EV_1KM_RefSB")));
	if (SDgetinfo(sds_id,NULL,&rank,dims,&type,&numattr) == -1) {
	    fHY1C_out(stderr,"-E- %s line %d: error getting dimension info.\n",
	    __FILE__,__LINE__);
	    return(HDF_FUNCTION_ERROR);
	}
	npix   = dims[2];
	nscan  = dims[1];
	if (getHDFattr(sd_id[2],"Extract Pixel Count","",(VOIDP)&itemp) == 0 && itemp > 0) {
	    npix  = itemp;
	    getHDFattr(sd_id[2],"Extract Pixel Offset","",(VOIDP)&itemp);
	    spix  = itemp;
	    getHDFattr(sd_id[2],"Extract Line Offset","",(VOIDP)&itemp);
	    sscan = itemp*nd1000;
	    have_extract = 1;
            if(want_verbose) {
                HY1C_out("File was generated from L1A extract of size %d x %d\n",npix,nscan);
                HY1C_out("  Pixels %d - %d\n",spix+1,spix+npix);
                HY1C_out("  Lines  %d - %d\n",sscan+1,sscan+nscan);
            } // want_verbose
        }
	ndet   = nd1000;
	np1000 = npix;
	sp1000 = spix;
	np500  = npix;
	sp500  = spix;
	get_modis_calfile(sd_id[2],file->calfile); /* read list of inputs to L1B */
	break;
    }

    file->npix   = npix;
    file->ndets  = ndet;
    file->nscan  = nscan;
    file->sd_id  = sd_id[2];


    /* Open the HDF geolocation input file.*/
    sd_id_g = SDstart(file->geofile, DFACC_RDONLY);
    if(sd_id_g == FAIL){
//	HY1C_out("Error opening geolocation file.\n");
//	    fHY1C_out(stderr,"-E- %s line %d: SDstart(%s, %d) failed.\n",
//	    __FILE__,__LINE__,file->geofile,DFACC_RDONLY);
//	return(HDF_FUNCTION_ERROR);
    }

     /* Has geolocation been corrected for terrain height? */
    if (getHDFattr(sd_id_g,"Cumulated gflags","",(VOIDP)&gflags) == 0) {
	file->terrain_corrected = (int32_t)(gflags[5]==0);
    } else HY1C_out("-E- %s line %d: Error reading gflags.\n",__FILE__,__LINE__);

    get_modis_orbit(sd_id_g, file); /* read orbit info */


    if (file->sensorID == HMODISA && resolution == 250) destripe=1;

    return(LIFE_IS_GOOD);
}


/* ----------------------------------------------------------------------------------- */
/* readl1_hmodis_hdf() - reads 1 line (scan) from a MODIS L1B file, loads l1rec.       */
/*                                                                                     */
/*
    Pos   Band   Wavelength      Resolution  EV_Position
      0      8       412            1000          0
      1      9       443            1000          1
      2      3       469             500            0
      3     10       488            1000          2
      4     11       531            1000          3
      5     12       551            1000          4
      6      4       555             500            1
      7      1       645             250              0
      8     13       667lo          1000          5
      9     14       678lo          1000          7
     10     15       748            1000          9
     11      2       858             250              1
     12     16       869            1000         10
     13      5      1240             500            2
     14      6      1640             500            3
     15      7      2130             500            4

     16     20      3750            1000
     17     22      3959            1000
     18     23      4050            1000
     19     27      6715            1000
     20     28      7325            1000
     21     29      8550            1000
     22     31     11030            1000
     23     32     12020            1000
 */

static void lognull() {}
//#define HY1C_READ_SDS_ID READ_SDS_ID
#define HY1C_READ_SDS_ID(...) lognull()

//#define HY1C_USE_HMODIS_MEMCOPY

int hy1c_readl1_hmodis_hdf(filehandle *file, int32 scan, l1str *l1rec, int lonlat)
{
    static int   firstCall = 1;
    static int   firstScan = 1;
    static float pi = PI;

    static uint16  *idata = NULL;
    static float32 *fdata = NULL;

    static  int16 *hgt  = NULL;
    static  int16 *senz = NULL;
    static  int16 *sena = NULL;
    static  int16 *solz = NULL;
    static  int16 *sola = NULL;

    int32  rank;
    int32  dims[3];
    int32  type;
    int32  numattr;
    int32  sds_id;

    static float m   [MAXBANDS];
    static float b   [MAXBANDS];
    static float mrad[MAXBANDS];
    static float brad[MAXBANDS];
    static float m_cirrus;
    static float b_cirrus;

    float floatbuf[15];

    static int nb250  = 2;
    static int ib250 [] = {7,11};
    static int pb250 [] = {0,1};

    static int nb500  = 5;
    static int ib500 [] = {2,6,13,14,15};
    static int pb500 [] = {0,1,2,3,4};

    static int nb1000 = 9;
    static int ib1000[] = {0,1,3,4,5,8,9,10,12};
    static int pb1000[] = {0,1,2,3,4,5,7, 9,10};

    static int nbir   = 8;
    static int ibir  [] = {16,17,18,19,20,21,22,23};
    static int pbir  [] = {0,2,3,6,7,8,10,11};

    static int nbcir  = 1;
    static int ibcir [] = {24};
    static int pbcir [] = {0};

    static float64 lastTAIsec = -1;
    static float64 TAIsec, usec, dsec;
    static int16  year, day;
    static int32  lday;
    static double fsol;
    static int16  mside, badmside;
    static double mnorm[3];
    static int32  lastframe = -1;
    static int32  last_work_scan;

    int32 npix   = (int32)file->npix;
    int32 nbands = (int32)file->nbands;
    int32 frame  = (rscan+scan) / ndet;
    int32 detnum = (rscan+scan) % ndet;
    int32 i,ip,iw,ib,ipb,status;
    int32 idet, iline;

    static float *Fobar;
    double hour;
    double esdist;

    if (firstCall) {

	firstCall = 0;

	/* We need this for the reflectance to radiance conversion */
	rdsensorinfo(file->sensorID,file->input->evalmask,"Fobar", (void **) &Fobar);

	/* Buffer for one line, all bands */
	if ((idata = (uint16 *) calloc(npix*MAXBANDS, sizeof(uint16))) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating data space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((fdata = (float32 *) calloc(npix*MAXBANDS, sizeof(float32))) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating data space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}

	/* Need to buffer a full (10-det) scan of 1km geolocation */
	if ((lon1000 = alloc2d_float(np1000,nd1000)) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating geolocation space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((lat1000 = alloc2d_float(np1000,nd1000)) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating geolocation space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((hgt1000 = alloc2d_float(np1000,nd1000)) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating geolocation space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((solz1000 = alloc2d_float(np1000,nd1000)) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating geolocation space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((sola1000 = alloc2d_float(np1000,nd1000)) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating geolocation space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((senz1000 = alloc2d_float(np1000,nd1000)) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating geolocation space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((sena1000 = alloc2d_float(np1000,nd1000)) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating geolocation space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}

	/* Need buffers for single scan of scaled values */
	if ((hgt = (int16 *) calloc(np1000, sizeof(int16))) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating hgt space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((solz = (int16 *) calloc(np1000, sizeof(int16))) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating solz space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((sola = (int16 *) calloc(np1000, sizeof(int16))) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating sola space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((senz = (int16 *) calloc(np1000, sizeof(int16))) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating senz space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((sena = (int16 *) calloc(np1000, sizeof(int16))) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating sena space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}

	if (resolution == 250) {

	      /* reflectance scale and offset factors */

	    if (getHDFattr(sd_id[0],"reflectance_scales","EV_250_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		   __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 m[ib250[ib]] = floatbuf[pb250[ib]];
	    if (getHDFattr(sd_id[0],"reflectance_offsets","EV_250_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 b[ib250[ib]] = floatbuf[pb250[ib]];

	    if (getHDFattr(sd_id[1],"reflectance_scales","EV_500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 m[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[1],"reflectance_offsets","EV_500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 b[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[2],"reflectance_scales","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		 m[ib1000[ib]] = floatbuf[pb1000[ib]];

	    if (getHDFattr(sd_id[2],"reflectance_offsets","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		     b[ib1000[ib]] = floatbuf[pb1000[ib]];

	      /* radiance scale and offset factors (for destriping subframes) */

	    if (getHDFattr(sd_id[0],"radiance_scales","EV_250_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance scale attribute.\n",
		   __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 mrad[ib250[ib]] = floatbuf[pb250[ib]];

	    if (getHDFattr(sd_id[0],"radiance_offsets","EV_250_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 brad[ib250[ib]] = floatbuf[pb250[ib]];

	    if (getHDFattr(sd_id[1],"radiance_scales","EV_500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 mrad[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[1],"radiance_offsets","EV_500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 brad[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[2],"radiance_scales","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		 mrad[ib1000[ib]] = floatbuf[pb1000[ib]];

	    if (getHDFattr(sd_id[2],"radiance_offsets","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		     brad[ib1000[ib]] = floatbuf[pb1000[ib]];



	    /* allocate data buffers for interpolation */

	    for (ib=0; ib<nb1000; ib++) {
		if ((fdatabuf[ib1000[ib]] = (float32 **) alloc2d_float(np1000,nd1000)) == NULL) {
		    HY1C_out("-E- %s line %d: Error allocating data buffer space for band %d\n",
			   __FILE__,__LINE__,ib1000[ib]);
		    exit(1);
		}
	    }

	    for (ib=0; ib<nbir; ib++) {
		if ((fdatabuf[ibir[ib]] = (float32 **) alloc2d_float(np1000,nd1000)) == NULL) {
		    HY1C_out("-E- %s line %d: Error allocating data buffer space for band %d\n",
			   __FILE__,__LINE__,ibir[ib]);
		    exit(1);
		}
	    }

	    for (ib=0; ib<nbcir; ib++) {
		if ((fdatabuf[ibcir[ib]] = (float32 **) alloc2d_float(np1000,nd1000)) == NULL) {
		    HY1C_out("-E- %s line %d: Error allocating data buffer space for band %d\n",
			   __FILE__,__LINE__,ibcir[ib]);
		    exit(1);
		}
	    }

	    for (ib=0; ib<nb500; ib++) {
		if ((fdatabuf[ib500[ib]] = (float32 **) alloc2d_float(np500,nd500)) == NULL) {
		    HY1C_out("-E- %s line %d: Error allocating data buffer space for band %d\n",
			   __FILE__,__LINE__,ib500[ib]);
		    exit(1);
		}
	    }

	} else if (resolution == 500) {

	      /* reflectance scale and offset factors */

	    if (getHDFattr(sd_id[1],"reflectance_scales","EV_250_Aggr500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		   __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 m[ib250[ib]] = floatbuf[pb250[ib]];
	    if (getHDFattr(sd_id[1],"reflectance_offsets","EV_250_Aggr500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 b[ib250[ib]] = floatbuf[pb250[ib]];

	    if (getHDFattr(sd_id[1],"reflectance_scales","EV_500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 m[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[1],"reflectance_offsets","EV_500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 b[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[2],"reflectance_scales","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		 m[ib1000[ib]] = floatbuf[pb1000[ib]];

	    if (getHDFattr(sd_id[2],"reflectance_offsets","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		     b[ib1000[ib]] = floatbuf[pb1000[ib]];

	    if (getHDFattr(sd_id[1],"reflectance_scales","EV_250_Aggr500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		   __FILE__,__LINE__);
		return(1);
	    }


	      /* radiance scale and offset factors (for destriping subframes) */

	    for (ib=0; ib<nb250; ib++)
		 mrad[ib250[ib]] = floatbuf[pb250[ib]];
	    if (getHDFattr(sd_id[1],"radiance_offsets","EV_250_Aggr500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 brad[ib250[ib]] = floatbuf[pb250[ib]];

	    if (getHDFattr(sd_id[1],"radiance_scales","EV_500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 mrad[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[1],"radiance_offsets","EV_500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 brad[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[2],"radiance_scales","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		 mrad[ib1000[ib]] = floatbuf[pb1000[ib]];

	    if (getHDFattr(sd_id[2],"radiance_offsets","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		     brad[ib1000[ib]] = floatbuf[pb1000[ib]];

	    /* allocate data buffers for interpolation */

	    for (ib=0; ib<nb1000; ib++) {
		if ((fdatabuf[ib1000[ib]] = (float32 **) alloc2d_float(np1000,nd1000)) == NULL) {
		    HY1C_out("-E- %s line %d: Error allocating data buffer space for band %d\n",
			   __FILE__,__LINE__,ib1000[ib]);
		    exit(1);
		}
	    }

	    for (ib=0; ib<nbir; ib++) {
		if ((fdatabuf[ibir[ib]] = (float32 **) alloc2d_float(np1000,nd1000)) == NULL) {
		    HY1C_out("-E- %s line %d: Error allocating data buffer space for band %d\n",
			   __FILE__,__LINE__,ibcir[ib]);
		    exit(1);
		}
	    }

	    for (ib=0; ib<nbcir; ib++) {
		if ((fdatabuf[ibcir[ib]] = (float32 **) alloc2d_float(np1000,nd1000)) == NULL) {
		    HY1C_out("-E- %s line %d: Error allocating data buffer space for band %d\n",
			   __FILE__,__LINE__,ibcir[ib]);
		    exit(1);
		}
	    }

	} else { /* 1KM */

	      /* reflectance scale and offset factors */

	    if (getHDFattr(sd_id[2],"reflectance_scales","EV_250_Aggr1km_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		   __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 m[ib250[ib]] = floatbuf[pb250[ib]];

	    if (getHDFattr(sd_id[2],"reflectance_offsets","EV_250_Aggr1km_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 b[ib250[ib]] = floatbuf[pb250[ib]];

	    if (getHDFattr(sd_id[2],"reflectance_scales","EV_500_Aggr1km_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 m[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[2],"reflectance_offsets","EV_500_Aggr1km_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 b[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[2],"reflectance_scales","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		 m[ib1000[ib]] = floatbuf[pb1000[ib]];

	    if (getHDFattr(sd_id[2],"reflectance_offsets","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		     b[ib1000[ib]] = floatbuf[pb1000[ib]];

	      /* radiance scale and offset factors (for destriping subframes) */

	    if (getHDFattr(sd_id[2],"radiance_scales","EV_250_Aggr1km_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance scale attribute.\n",
		   __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 mrad[ib250[ib]] = floatbuf[pb250[ib]];

	    if (getHDFattr(sd_id[2],"radiance_offsets","EV_250_Aggr1km_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 brad[ib250[ib]] = floatbuf[pb250[ib]];

	    if (getHDFattr(sd_id[2],"radiance_scales","EV_500_Aggr1km_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 mrad[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[2],"radiance_offsets","EV_500_Aggr1km_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 brad[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[2],"radiance_scales","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		 mrad[ib1000[ib]] = floatbuf[pb1000[ib]];

	    if (getHDFattr(sd_id[2],"radiance_offsets","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		     brad[ib1000[ib]] = floatbuf[pb1000[ib]];
	}

	/* radiance scale and offset factors for emmissive bands */

	if (getHDFattr(sd_id[2],"radiance_scales","EV_1KM_Emissive",(VOIDP)floatbuf) != 0) {
	    HY1C_out("-E- %s line %d: Error reading emissive radiance scale attribute.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	for (ib=0; ib<nbir; ib++)
	     mrad[ibir[ib]] = floatbuf[pbir[ib]];

	if (getHDFattr(sd_id[2],"radiance_offsets","EV_1KM_Emissive",(VOIDP)floatbuf) != 0) {
	    HY1C_out("-E- %s line %d: Error reading emissive radiance offset attribute.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	for (ib=0; ib<nbir; ib++)
		 brad[ibir[ib]] = floatbuf[pbir[ib]];

	/* rreflectance scale and offset factors for cirrus band */

	if (getHDFattr(sd_id[2],"reflectance_scales","EV_Band26",(VOIDP)&m_cirrus) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	}

	if (getHDFattr(sd_id[2],"reflectance_offsets","EV_Band26",(VOIDP)&b_cirrus) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
	    return(1);
	}
    }

    for (ip=0; ip<npix; ip++)
	l1rec->pixnum[ip] = spix + ip;

    if (frame != lastframe) {

	/* Get mirror side (0=A,1=B) and mirror normal (in ECR) */
	HY1C_READ_SDS_ID(sd_id_g,"Mirror side",&mside, frame,0,0,0, 1,1,1,1);
	HY1C_READ_SDS_ID(sd_id_g,"T_inst2ECR" ,&mnorm, frame,0,0,0, 1,3,1,1);

	/* Fix mirror-side if set to -1 in geolocation (used as array index) */
	if (mside < 0) {
	    mside = 0;
	    badmside = 1;
	} else
	    badmside = 0;

	/* Read granule time and compute scan times */
	HY1C_READ_SDS_ID(sd_id_g,"EV start time",(float64 *)&TAIsec, frame,0,0,0, 1,1,1,1);

	/* Work-around for single-scan time errors */
	if (TAIsec < 0.0) {
	    HY1C_out("-W- %s: bad time in geolocation file at frame %d, using previous.\n",
		__FILE__,frame);
	    TAIsec = lastTAIsec;
	} else
	    lastTAIsec = TAIsec;

	usec = TAIsec + 725846400.0;
	unix2yds(usec,&year,&day,&dsec);

	*(l1rec->year) = (int32_t)year;
	*(l1rec->day)  = (int32_t)day;
	*(l1rec->msec) = (int32_t)(dsec*1000.0);

	/* Get earth-sun distance correction for this frame */
	esdist = esdist_(l1rec->year,l1rec->day,l1rec->msec);
	fsol   = pow(1.0/esdist,2);

	/* Load 1km geolocation buffer */
	for (idet=0; idet<nd1000; idet++) {
	  iline = frame * nd1000 + idet;
	  HY1C_READ_SDS_ID(sd_id_g,"Longitude",&lon1000[idet][0], iline,sp1000,0,0, 1,np1000,1,1);
	  HY1C_READ_SDS_ID(sd_id_g,"Latitude" ,&lat1000[idet][0], iline,sp1000,0,0, 1,np1000,1,1);
	  if(!lonlat) {
	    HY1C_READ_SDS_ID(sd_id_g,"Height"        ,hgt,  iline,sp1000,0,0, 1,np1000,1,1);
	    HY1C_READ_SDS_ID(sd_id_g,"SolarZenith"   ,solz, iline,sp1000,0,0, 1,np1000,1,1);
	    HY1C_READ_SDS_ID(sd_id_g,"SolarAzimuth"  ,sola, iline,sp1000,0,0, 1,np1000,1,1);
	    HY1C_READ_SDS_ID(sd_id_g,"SensorZenith"  ,senz, iline,sp1000,0,0, 1,np1000,1,1);
	    HY1C_READ_SDS_ID(sd_id_g,"SensorAzimuth" ,sena, iline,sp1000,0,0, 1,np1000,1,1);
	    for (ip=0; ip<np1000; ip++) {
	      hgt1000[idet][ip]  = (float)hgt[ip];
	      solz1000[idet][ip] = (float)solz[ip] * 0.01;
	      sola1000[idet][ip] = (float)sola[ip] * 0.01;
	      senz1000[idet][ip] = (float)senz[ip] * 0.01;
	      sena1000[idet][ip] = (float)sena[ip] * 0.01;
	    }
	  } // if not lonlat
	}

	/* Load data buffers, if required */

	if(!lonlat) {
	    if (resolution < 1000) {
		for (iw=0; iw<nb1000; iw++) {
		    ib = ib1000[iw];
		    for (idet=0; idet<nd1000; idet++) {
			iline = frame * nd1000 + idet;
			HY1C_READ_SDS_ID(sd_id[2],"EV_1KM_RefSB",&idata[ib*npix], pb1000[iw],iline,sp1000,0,1,1,np1000,1);
			for (ip=0; ip<np1000; ip++)
			    fdatabuf[ib][idet][ip] = (float) idata[ib*npix+ip];
		    }
		}
		for (iw=0; iw<nbir; iw++) {
		    ib = ibir[iw];
		    for (idet=0; idet<nd1000; idet++) {
			iline = frame * nd1000 + idet;
			HY1C_READ_SDS_ID(sd_id[2],"EV_1KM_Emissive",&idata[ib*npix], pbir[iw],iline,sp1000,0,1,1,np1000,1);
			for (ip=0; ip<np1000; ip++)
			    fdatabuf[ib][idet][ip] = (float) idata[ib*npix+ip];
		    }
		}
		for (iw=0; iw<nbcir; iw++) {
		    ib = ibcir[iw];
		    for (idet=0; idet<nd1000; idet++) {
			iline = frame * nd1000 + idet;
			HY1C_READ_SDS_ID(sd_id[2],"EV_Band26",&idata[ib*npix], iline,sp1000,0,0,1,np1000,1,1);
			for (ip=0; ip<np1000; ip++)
			    fdatabuf[ib][idet][ip] = (float) idata[ib*npix+ip];
		    }
		}
	    }

	    if (resolution < 500) {
		for (iw=0; iw<nb500; iw++) {
		    ib = ib500[iw];
		    for (idet=0; idet<nd500; idet++) {
			iline = frame * nd500 + idet;
			HY1C_READ_SDS_ID(sd_id[1],"EV_500_RefSB",&idata[ib*npix], pb500[iw],iline,sp500,0,1,1,np500,1);
			for (ip=0; ip<np500; ip++)
			    fdatabuf[ib][idet][ip] = (float) idata[ib*npix+ip];
			if (destripe) {
			    subframe_calibration(l1rec->sensorID,ib,mrad[ib],brad[ib],sp500,np500,&fdatabuf[ib][idet][0]);
			}
		    }
		}
	    }
	} // if not lonlat

	lastframe = frame;
    }

    *(l1rec->year) = (int32_t)year;
    *(l1rec->day)  = (int32_t)day;
    *(l1rec->msec) = (int32_t)(dsec*1000.0);


    /* Get position and path geometry */

    switch (resolution) {
    case 250:
    case 500:
      for (ip=0; ip<npix; ip++)
	modis_geo_interp(ip,detnum,resolution,
			 &l1rec->lon [ip], &l1rec->lat [ip], &l1rec->height[ip],
			 &l1rec->solz[ip], &l1rec->sola[ip],
			 &l1rec->senz[ip], &l1rec->sena[ip], lonlat);
      break;
    default:
#ifdef HY1C_USE_HMODIS_MEMCOPY
     memcpy(l1rec->lon,   &lon1000 [detnum][0],npix*sizeof(float32));
     memcpy(l1rec->lat,   &lat1000 [detnum][0],npix*sizeof(float32));
#endif
      if(!lonlat) {
#ifdef HY1C_USE_HMODIS_MEMCOPY
    memcpy(l1rec->height,&hgt1000 [detnum][0],npix*sizeof(float32));
    memcpy(l1rec->solz,  &solz1000[detnum][0],npix*sizeof(float32));
    memcpy(l1rec->sola,  &sola1000[detnum][0],npix*sizeof(float32));
    memcpy(l1rec->senz,  &senz1000[detnum][0],npix*sizeof(float32));
    memcpy(l1rec->sena,  &sena1000[detnum][0],npix*sizeof(float32));
#endif
      } // if not lonlat
      break;
    }

    if(lonlat) {
	return(LIFE_IS_GOOD);
    }


    /* Check for nav errors */
/*
    for (ip=0; ip<npix; ip++) {
	if (l1rec->lon[ip] < -181.0 || l1rec->lon[ip] > 181.0 ||
	    l1rec->lat[ip] <  -91.0 || l1rec->lat[ip] >  91.0 ||
	    badmside)
	  l1rec->navfail[ip] = 1;
    }
    */

    /* Compute polarization frame rotation angles */
    compute_alpha(l1rec->lon, l1rec->lat, l1rec->senz, l1rec->sena,
		  mnorm, npix, l1rec->alpha);


    /* Read L1B VNIR data, scale to radiance, and copy relevant bands to L1 record  */
    /* MODIS format is band sequential.  We want band interlaced.  We use imbedded  */
    /* scale factors to get reflectance, then convert to radiance through mean F0.  */
    /* Note that use of MCST radiance scale factor gives different result.          */

    switch (resolution) {
      case 250:
	for (iw=0; iw<nb250; iw++) {
	    ib = ib250[iw];
	    HY1C_READ_SDS_ID(sd_id[0],"EV_250_RefSB",&idata[ib*npix], pb250[iw],scan,spix,0,1,1,npix,1);
	    for (ip=0; ip<npix; ip++)
		fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
	    if (destripe) {
		  subframe_calibration(l1rec->sensorID,ib,mrad[ib],brad[ib],spix,npix,&fdata[ib*npix]);
	    }
	}
	for (iw=0; iw<nb500; iw++) {
	    ib = ib500[iw];
	    for (ip=0; ip<npix; ip++) {
		modis_data_interp(ib,ip,detnum,500,250,&fdata[ib*npix+ip]);
		idata[ib*npix+ip] = (uint16) rint(fdata[ib*npix+ip]);
	    }
	}
	for (iw=0; iw<nb1000; iw++) {
	    ib = ib1000[iw];
	    for (ip=0; ip<npix; ip++) {
		modis_data_interp(ib,ip,detnum,1000,250,&fdata[ib*npix+ip]);
		idata[ib*npix+ip] = (uint16) rint(fdata[ib*npix+ip]);
	    }
	}
	for (iw=0; iw<nbir; iw++) {
	    ib = ibir[iw];
	    for (ip=0; ip<npix; ip++) {
		modis_data_interp(ib,ip,detnum,1000,250,&fdata[ib*npix+ip]);
		idata[ib*npix+ip] = (uint16) rint(fdata[ib*npix+ip]);
	    }
	}
	for (iw=0; iw<nbcir; iw++) {
	    ib = ibcir[iw];
	    for (ip=0; ip<npix; ip++) {
		modis_data_interp(ib,ip,detnum,1000,250,&fdata[ib*npix+ip]);
		idata[ib*npix+ip] = (uint16) rint(fdata[ib*npix+ip]);
	    }
	}
	break;

      case 500:
	for (iw=0; iw<nb250; iw++) {
	    ib = ib250[iw];
	    HY1C_READ_SDS_ID(sd_id[1],"EV_250_Aggr500_RefSB",&idata[ib*npix], pb250[iw],scan,spix,0,1,1,npix,1);
	    for (ip=0; ip<npix; ip++)
		fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
	}
	for (iw=0; iw<nb500; iw++) {
	    ib = ib500[iw];
	    HY1C_READ_SDS_ID(sd_id[1],"EV_500_RefSB",&idata[ib*npix], pb500[iw],scan,spix,0,1,1,npix,1);
	    for (ip=0; ip<npix; ip++)
		fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
	    if (destripe) {
		  subframe_calibration(l1rec->sensorID,ib,mrad[ib],brad[ib],spix,npix,&fdata[ib*npix]);
	    }
	}
	for (iw=0; iw<nb1000; iw++) {
	    ib = ib1000[iw];
	    for (ip=0; ip<npix; ip++) {
		modis_data_interp(ib,ip,detnum,1000,500,&fdata[ib*npix+ip]);
		idata[ib*npix+ip] = (uint16) rint(fdata[ib*npix+ip]);
	    }
	}
	for (iw=0; iw<nbir; iw++) {
	    ib = ibir[iw];
	    for (ip=0; ip<npix; ip++) {
		modis_data_interp(ib,ip,detnum,1000,500,&fdata[ib*npix+ip]);
		idata[ib*npix+ip] = (uint16) rint(fdata[ib*npix+ip]);
	    }
	}
	for (iw=0; iw<nbcir; iw++) {
	    ib = ibcir[iw];
	    for (ip=0; ip<npix; ip++) {
		modis_data_interp(ib,ip,detnum,1000,500,&fdata[ib*npix+ip]);
		idata[ib*npix+ip] = (uint16) rint(fdata[ib*npix+ip]);
	    }
	}
	break;

      default:
    for (iw=0; iw<nb250; iw++) {
        ib = ib250[iw];
        HY1C_READ_SDS_ID(sd_id[2],"EV_250_Aggr1km_RefSB",&idata[ib*npix], pb250[iw],scan,spix,0,1,1,npix,1);
        for (ip=0; ip<npix; ip++)
        fdata[ib*npix+ip] = (float) idata[ib*npix+ip];

    }
    for (iw=0; iw<nb500; iw++) {
        ib = ib500[iw];
        HY1C_READ_SDS_ID(sd_id[2],"EV_500_Aggr1km_RefSB",&idata[ib*npix], pb500[iw],scan,spix,0,1,1,npix,1);
        for (ip=0; ip<npix; ip++)
        fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
    }
    for (iw=0; iw<nb1000; iw++) {
        ib = ib1000[iw];
        HY1C_READ_SDS_ID(sd_id[2],"EV_1KM_RefSB",&idata[ib*npix], pb1000[iw],scan,spix,0,1,1,npix,1);
        for (ip=0; ip<npix; ip++)
        fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
    }
    for (iw=0; iw<nbir; iw++) {
        ib = ibir[iw];
        HY1C_READ_SDS_ID(sd_id[2],"EV_1KM_Emissive",&idata[ib*npix], pbir[iw],scan,spix,0,1,1,npix,1);
        for (ip=0; ip<npix; ip++)
        fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
    }
    for (iw=0; iw<nbcir; iw++) {
        ib = ibcir[iw];
        HY1C_READ_SDS_ID(sd_id[2],"EV_Band26",&idata[ib*npix], scan,spix,0,0, 1,npix,1,1);
        for (ip=0; ip<npix; ip++)
        fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
    }
        for (iw=0; iw<nb250; iw++) {
            ib = ib250[iw];
            HY1C_READ_SDS_ID(sd_id[2],"EV_250_Aggr1km_RefSB",&idata[ib*npix], pb250[iw],scan,spix,0,1,1,npix,1);
            for (ip=0; ip<npix; ip++)
            fdata[ib*npix+ip] = (float) idata[ib*npix+ip];

        }
        for (iw=0; iw<nb500; iw++) {
            ib = ib500[iw];
            HY1C_READ_SDS_ID(sd_id[2],"EV_500_Aggr1km_RefSB",&idata[ib*npix], pb500[iw],scan,spix,0,1,1,npix,1);
            for (ip=0; ip<npix; ip++)
            fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
        }
        for (iw=0; iw<nb1000; iw++) {
            ib = ib1000[iw];
            HY1C_READ_SDS_ID(sd_id[2],"EV_1KM_RefSB",&idata[ib*npix], pb1000[iw],scan,spix,0,1,1,npix,1);
            for (ip=0; ip<npix; ip++)
            fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
        }
        for (iw=0; iw<nbir; iw++) {
            ib = ibir[iw];
            HY1C_READ_SDS_ID(sd_id[2],"EV_1KM_Emissive",&idata[ib*npix], pbir[iw],scan,spix,0,1,1,npix,1);
            for (ip=0; ip<npix; ip++)
            fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
        }
        for (iw=0; iw<nbcir; iw++) {
            ib = ibcir[iw];
            HY1C_READ_SDS_ID(sd_id[2],"EV_Band26",&idata[ib*npix], scan,spix,0,0, 1,npix,1,1);
            for (ip=0; ip<npix; ip++)
            fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
        }
    break;
    }

    for (iw=0; iw<nbands; iw++) {

	l1rec->Fo[iw] = Fobar[iw] * fsol;

#if 0
    for (ip=0; ip<npix; ip++) {

        ipb = ip*NBANDS+iw;
	    l1rec->Lt[ipb] = BAD_FLT;

	    /* skip night data for visible bands */
	    if (l1rec->solz[ip] >= SOLZNIGHT)
        continue;

	    /* check for sentinel values and flag as appropriate */
	    if (idata[iw*npix+ip] >= 65500) {
		  switch (idata[iw*npix+ip]) {
		  case 65527: /* not in earth view */
		     l1rec->navfail[ip] = 1;
		    break;
                  case 65529: /* saturation */
                  case 65533:
		    l1rec->Lt[ipb] = 1000.0;
            if (iw <= 12) l1rec->hilt[ip] = 1;
		  default:    /* other stuff */
		    break;
		}

	    } else
		l1rec->Lt[ipb] = (fdata[iw*npix+ip] - b[iw]) * m[iw] * l1rec->Fo[iw]/pi;
    }
   #endif
    }

    for (iw=nbands; iw<nbands+nbir; iw++) {

	ib = iw-nbands;

	switch (resolution) {
	  case  250: idet=detnum/4; break;
	  case  500: idet=detnum/2; break;
	  case 1000: idet=detnum/1; break;
	}

	for (ip=0; ip<npix; ip++) {

        ipb = ip*NBANDSIR+ib;
	    l1rec->Ltir[ipb] = 0.0;

	    if (idata[iw*npix+ip] >= 65500) {
		;
	    } else {

		l1rec->Ltir[ipb] = (fdata[iw*npix+ip] - brad[iw]) * mrad[iw]/10.0;


		if (l1rec->sensorID == MODIST || l1rec->sensorID == HMODIST) {
		    l1rec->Ltir[ipb] *= (1.0-radoff[ib][idet]);
		    if (mside == 1) l1rec->Ltir[ipb] *= (1.0 + mfact[ib]);
		}
		if (((file->input->evalmask & SSTMODS) != 0) &&
		    (l1rec->sensorID == MODISA || l1rec->sensorID == HMODISA)) {
		    if (iw == 0 && detnum == 2-1) {
			l1rec->Ltir[ipb] *= ch20d2cor;
		    } else if (iw == 0 && detnum == 3-1) {
			l1rec->Ltir[ipb] *= ch20d3cor;
		    } else if (iw == 0 && detnum == 10-1) {
			l1rec->Ltir[ipb] *= ch20d10cor;
		    } else if (iw == 1 && detnum == 1-1) {
			l1rec->Ltir[ipb] *= ch22d1cor;
		    } else if (iw == 1 && detnum == 8-1) {
			l1rec->Ltir[ipb] *= ch22d8cor;
		    } else if (iw == 1 && detnum == 9-1) {
			l1rec->Ltir[ipb] *= ch22d9cor;
		    } else if (iw == 1 && detnum == 10-1) {
			l1rec->Ltir[ipb] *= ch22d10cor;
		    } else if (iw == 2 && detnum == 1-1) {
			l1rec->Ltir[ipb] *= ch23d1cor;
		    }
		}
	    }
	}
    }

    /* Read cirrus band */

    for (ip=0; ip<npix; ip++) {
	ib = ibcir[0];
	l1rec->rho_cirrus[ip] = 0.0;
	if (idata[iw*npix+ip] < 65500) {
	    l1rec->rho_cirrus[ip] = (fdata[ib*npix+ip] - b_cirrus) * m_cirrus / cos(l1rec->solz[ip]/RADEG);
	 }
    }

    firstScan = 0;

    l1rec->sensorID = file->sensorID;
    l1rec->npix     = file->npix;
    l1rec->detnum   = (int32_t)detnum;
    l1rec->mside    = (int32_t)mside;

    /* Convert IR bands to brightness temperature */
    radiance2bt(l1rec,resolution);

    return(LIFE_IS_GOOD);

}

/*                                                                                     */
/* B. Franz, SAIC, February 2006.                                                      */
/* ----------------------------------------------------------------------------------- */
int readl1_hmodis_hdf(filehandle *file, int32 scan, l1str *l1rec, int lonlat)
{
    static int   firstCall = 1;
    static int   firstScan = 1;
    static float pi = PI;

    static uint16  *idata = NULL;
    static float32 *fdata = NULL;

    static  int16 *hgt  = NULL;
    static  int16 *senz = NULL;
    static  int16 *sena = NULL;
    static  int16 *solz = NULL;
    static  int16 *sola = NULL;

    int32  rank;
    int32  dims[3];
    int32  type;
    int32  numattr;
    int32  sds_id;

    static float m   [MAXBANDS];
    static float b   [MAXBANDS];
    static float mrad[MAXBANDS];
    static float brad[MAXBANDS];
    static float m_cirrus;
    static float b_cirrus;

    float floatbuf[15];

    static int nb250  = 2;
    static int ib250 [] = {7,11};
    static int pb250 [] = {0,1};

    static int nb500  = 5;
    static int ib500 [] = {2,6,13,14,15};
    static int pb500 [] = {0,1,2,3,4};

    static int nb1000 = 9;
    static int ib1000[] = {0,1,3,4,5,8,9,10,12};
    static int pb1000[] = {0,1,2,3,4,5,7, 9,10};

    static int nbir   = 8;
    static int ibir  [] = {16,17,18,19,20,21,22,23};
    static int pbir  [] = {0,2,3,6,7,8,10,11};

    static int nbcir  = 1;
    static int ibcir [] = {24};
    static int pbcir [] = {0};

    static float64 lastTAIsec = -1;
    static float64 TAIsec, usec, dsec;
    static int16  year, day;
    static int32  lday;
    static double fsol;
    static int16  mside, badmside;
    static double mnorm[3];
    static int32  lastframe = -1;
    static int32  last_work_scan;

    int32 npix   = (int32)file->npix;
    int32 nbands = (int32)file->nbands;
    int32 frame  = (rscan+scan) / ndet;
    int32 detnum = (rscan+scan) % ndet;
    int32 i,ip,iw,ib,ipb,status;
    int32 idet, iline;

    static float *Fobar;
    double hour;
    double esdist;

    if (firstCall) {

	firstCall = 0;

	/* We need this for the reflectance to radiance conversion */
	rdsensorinfo(file->sensorID,file->input->evalmask,"Fobar", (void **) &Fobar);

	/* Buffer for one line, all bands */
	if ((idata = (uint16 *) calloc(npix*MAXBANDS, sizeof(uint16))) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating data space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((fdata = (float32 *) calloc(npix*MAXBANDS, sizeof(float32))) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating data space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}

	/* Need to buffer a full (10-det) scan of 1km geolocation */
	if ((lon1000 = alloc2d_float(np1000,nd1000)) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating geolocation space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((lat1000 = alloc2d_float(np1000,nd1000)) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating geolocation space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((hgt1000 = alloc2d_float(np1000,nd1000)) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating geolocation space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((solz1000 = alloc2d_float(np1000,nd1000)) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating geolocation space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((sola1000 = alloc2d_float(np1000,nd1000)) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating geolocation space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((senz1000 = alloc2d_float(np1000,nd1000)) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating geolocation space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((sena1000 = alloc2d_float(np1000,nd1000)) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating geolocation space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}

	/* Need buffers for single scan of scaled values */
	if ((hgt = (int16 *) calloc(np1000, sizeof(int16))) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating hgt space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((solz = (int16 *) calloc(np1000, sizeof(int16))) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating solz space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((sola = (int16 *) calloc(np1000, sizeof(int16))) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating sola space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((senz = (int16 *) calloc(np1000, sizeof(int16))) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating senz space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	if ((sena = (int16 *) calloc(np1000, sizeof(int16))) == NULL) {
	    HY1C_out("-E- %s line %d: Error allocating sena space.\n",
		   __FILE__,__LINE__);
	    return(1);
	}

	if (resolution == 250) {

	      /* reflectance scale and offset factors */

	    if (getHDFattr(sd_id[0],"reflectance_scales","EV_250_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		   __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 m[ib250[ib]] = floatbuf[pb250[ib]];
	    if (getHDFattr(sd_id[0],"reflectance_offsets","EV_250_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 b[ib250[ib]] = floatbuf[pb250[ib]];

	    if (getHDFattr(sd_id[1],"reflectance_scales","EV_500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 m[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[1],"reflectance_offsets","EV_500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 b[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[2],"reflectance_scales","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		 m[ib1000[ib]] = floatbuf[pb1000[ib]];

	    if (getHDFattr(sd_id[2],"reflectance_offsets","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		     b[ib1000[ib]] = floatbuf[pb1000[ib]];

	      /* radiance scale and offset factors (for destriping subframes) */

	    if (getHDFattr(sd_id[0],"radiance_scales","EV_250_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance scale attribute.\n",
		   __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 mrad[ib250[ib]] = floatbuf[pb250[ib]];

	    if (getHDFattr(sd_id[0],"radiance_offsets","EV_250_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 brad[ib250[ib]] = floatbuf[pb250[ib]];

	    if (getHDFattr(sd_id[1],"radiance_scales","EV_500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 mrad[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[1],"radiance_offsets","EV_500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 brad[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[2],"radiance_scales","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		 mrad[ib1000[ib]] = floatbuf[pb1000[ib]];

	    if (getHDFattr(sd_id[2],"radiance_offsets","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		     brad[ib1000[ib]] = floatbuf[pb1000[ib]];



	    /* allocate data buffers for interpolation */

	    for (ib=0; ib<nb1000; ib++) {
		if ((fdatabuf[ib1000[ib]] = (float32 **) alloc2d_float(np1000,nd1000)) == NULL) {
		    HY1C_out("-E- %s line %d: Error allocating data buffer space for band %d\n",
			   __FILE__,__LINE__,ib1000[ib]);
		    exit(1);
		}
	    }

	    for (ib=0; ib<nbir; ib++) {
		if ((fdatabuf[ibir[ib]] = (float32 **) alloc2d_float(np1000,nd1000)) == NULL) {
		    HY1C_out("-E- %s line %d: Error allocating data buffer space for band %d\n",
			   __FILE__,__LINE__,ibir[ib]);
		    exit(1);
		}
	    }

	    for (ib=0; ib<nbcir; ib++) {
		if ((fdatabuf[ibcir[ib]] = (float32 **) alloc2d_float(np1000,nd1000)) == NULL) {
		    HY1C_out("-E- %s line %d: Error allocating data buffer space for band %d\n",
			   __FILE__,__LINE__,ibcir[ib]);
		    exit(1);
		}
	    }

	    for (ib=0; ib<nb500; ib++) {
		if ((fdatabuf[ib500[ib]] = (float32 **) alloc2d_float(np500,nd500)) == NULL) {
		    HY1C_out("-E- %s line %d: Error allocating data buffer space for band %d\n",
			   __FILE__,__LINE__,ib500[ib]);
		    exit(1);
		}
	    }

	} else if (resolution == 500) {

	      /* reflectance scale and offset factors */

	    if (getHDFattr(sd_id[1],"reflectance_scales","EV_250_Aggr500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		   __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 m[ib250[ib]] = floatbuf[pb250[ib]];
	    if (getHDFattr(sd_id[1],"reflectance_offsets","EV_250_Aggr500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 b[ib250[ib]] = floatbuf[pb250[ib]];

	    if (getHDFattr(sd_id[1],"reflectance_scales","EV_500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 m[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[1],"reflectance_offsets","EV_500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 b[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[2],"reflectance_scales","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		 m[ib1000[ib]] = floatbuf[pb1000[ib]];

	    if (getHDFattr(sd_id[2],"reflectance_offsets","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		     b[ib1000[ib]] = floatbuf[pb1000[ib]];

	    if (getHDFattr(sd_id[1],"reflectance_scales","EV_250_Aggr500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		   __FILE__,__LINE__);
		return(1);
	    }


	      /* radiance scale and offset factors (for destriping subframes) */

	    for (ib=0; ib<nb250; ib++)
		 mrad[ib250[ib]] = floatbuf[pb250[ib]];
	    if (getHDFattr(sd_id[1],"radiance_offsets","EV_250_Aggr500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 brad[ib250[ib]] = floatbuf[pb250[ib]];

	    if (getHDFattr(sd_id[1],"radiance_scales","EV_500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 mrad[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[1],"radiance_offsets","EV_500_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 brad[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[2],"radiance_scales","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		 mrad[ib1000[ib]] = floatbuf[pb1000[ib]];

	    if (getHDFattr(sd_id[2],"radiance_offsets","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		     brad[ib1000[ib]] = floatbuf[pb1000[ib]];

	    /* allocate data buffers for interpolation */

	    for (ib=0; ib<nb1000; ib++) {
		if ((fdatabuf[ib1000[ib]] = (float32 **) alloc2d_float(np1000,nd1000)) == NULL) {
		    HY1C_out("-E- %s line %d: Error allocating data buffer space for band %d\n",
			   __FILE__,__LINE__,ib1000[ib]);
		    exit(1);
		}
	    }

	    for (ib=0; ib<nbir; ib++) {
		if ((fdatabuf[ibir[ib]] = (float32 **) alloc2d_float(np1000,nd1000)) == NULL) {
		    HY1C_out("-E- %s line %d: Error allocating data buffer space for band %d\n",
			   __FILE__,__LINE__,ibcir[ib]);
		    exit(1);
		}
	    }

	    for (ib=0; ib<nbcir; ib++) {
		if ((fdatabuf[ibcir[ib]] = (float32 **) alloc2d_float(np1000,nd1000)) == NULL) {
		    HY1C_out("-E- %s line %d: Error allocating data buffer space for band %d\n",
			   __FILE__,__LINE__,ibcir[ib]);
		    exit(1);
		}
	    }

	} else { /* 1KM */

	      /* reflectance scale and offset factors */

	    if (getHDFattr(sd_id[2],"reflectance_scales","EV_250_Aggr1km_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		   __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 m[ib250[ib]] = floatbuf[pb250[ib]];

	    if (getHDFattr(sd_id[2],"reflectance_offsets","EV_250_Aggr1km_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 b[ib250[ib]] = floatbuf[pb250[ib]];

	    if (getHDFattr(sd_id[2],"reflectance_scales","EV_500_Aggr1km_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 m[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[2],"reflectance_offsets","EV_500_Aggr1km_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 b[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[2],"reflectance_scales","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		 m[ib1000[ib]] = floatbuf[pb1000[ib]];

	    if (getHDFattr(sd_id[2],"reflectance_offsets","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		     b[ib1000[ib]] = floatbuf[pb1000[ib]];

	      /* radiance scale and offset factors (for destriping subframes) */

	    if (getHDFattr(sd_id[2],"radiance_scales","EV_250_Aggr1km_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance scale attribute.\n",
		   __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 mrad[ib250[ib]] = floatbuf[pb250[ib]];

	    if (getHDFattr(sd_id[2],"radiance_offsets","EV_250_Aggr1km_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb250; ib++)
		 brad[ib250[ib]] = floatbuf[pb250[ib]];

	    if (getHDFattr(sd_id[2],"radiance_scales","EV_500_Aggr1km_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 mrad[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[2],"radiance_offsets","EV_500_Aggr1km_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb500; ib++)
		 brad[ib500[ib]] = floatbuf[pb500[ib]];

	    if (getHDFattr(sd_id[2],"radiance_scales","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		 mrad[ib1000[ib]] = floatbuf[pb1000[ib]];

	    if (getHDFattr(sd_id[2],"radiance_offsets","EV_1KM_RefSB",(VOIDP)floatbuf) != 0) {
		HY1C_out("-E- %s line %d: Error reading radiance offset attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	    }
	    for (ib=0; ib<nb1000; ib++)
		     brad[ib1000[ib]] = floatbuf[pb1000[ib]];
	}

	/* radiance scale and offset factors for emmissive bands */

	if (getHDFattr(sd_id[2],"radiance_scales","EV_1KM_Emissive",(VOIDP)floatbuf) != 0) {
	    HY1C_out("-E- %s line %d: Error reading emissive radiance scale attribute.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	for (ib=0; ib<nbir; ib++)
	     mrad[ibir[ib]] = floatbuf[pbir[ib]];

	if (getHDFattr(sd_id[2],"radiance_offsets","EV_1KM_Emissive",(VOIDP)floatbuf) != 0) {
	    HY1C_out("-E- %s line %d: Error reading emissive radiance offset attribute.\n",
		   __FILE__,__LINE__);
	    return(1);
	}
	for (ib=0; ib<nbir; ib++)
		 brad[ibir[ib]] = floatbuf[pbir[ib]];

	/* rreflectance scale and offset factors for cirrus band */

	if (getHDFattr(sd_id[2],"reflectance_scales","EV_Band26",(VOIDP)&m_cirrus) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance scale attribute.\n",
		       __FILE__,__LINE__);
		return(1);
	}

	if (getHDFattr(sd_id[2],"reflectance_offsets","EV_Band26",(VOIDP)&b_cirrus) != 0) {
		HY1C_out("-E- %s line %d: Error reading reflectance offset attribute.\n",
		       __FILE__,__LINE__);
	    return(1);
	}
    }

    for (ip=0; ip<npix; ip++)
	l1rec->pixnum[ip] = spix + ip;

    if (frame != lastframe) {

	/* Get mirror side (0=A,1=B) and mirror normal (in ECR) */
	READ_SDS_ID(sd_id_g,"Mirror side",&mside, frame,0,0,0, 1,1,1,1);
	READ_SDS_ID(sd_id_g,"T_inst2ECR" ,&mnorm, frame,0,0,0, 1,3,1,1);

	/* Fix mirror-side if set to -1 in geolocation (used as array index) */
	if (mside < 0) {
	    mside = 0;
	    badmside = 1;
	} else
	    badmside = 0;

	/* Read granule time and compute scan times */
	READ_SDS_ID(sd_id_g,"EV start time",(float64 *)&TAIsec, frame,0,0,0, 1,1,1,1);

	/* Work-around for single-scan time errors */
	if (TAIsec < 0.0) {
	    HY1C_out("-W- %s: bad time in geolocation file at frame %d, using previous.\n",
		__FILE__,frame);
	    TAIsec = lastTAIsec;
	} else
	    lastTAIsec = TAIsec;

	usec = TAIsec + 725846400.0;
	unix2yds(usec,&year,&day,&dsec);

	*(l1rec->year) = (int32_t)year;
	*(l1rec->day)  = (int32_t)day;
	*(l1rec->msec) = (int32_t)(dsec*1000.0);

	/* Get earth-sun distance correction for this frame */
	esdist = esdist_(l1rec->year,l1rec->day,l1rec->msec);
	fsol   = pow(1.0/esdist,2);

	/* Load 1km geolocation buffer */
	for (idet=0; idet<nd1000; idet++) {
	  iline = frame * nd1000 + idet;
	  READ_SDS_ID(sd_id_g,"Longitude",&lon1000[idet][0], iline,sp1000,0,0, 1,np1000,1,1);
	  READ_SDS_ID(sd_id_g,"Latitude" ,&lat1000[idet][0], iline,sp1000,0,0, 1,np1000,1,1);
	  if(!lonlat) {
	    READ_SDS_ID(sd_id_g,"Height"        ,hgt,  iline,sp1000,0,0, 1,np1000,1,1);
	    READ_SDS_ID(sd_id_g,"SolarZenith"   ,solz, iline,sp1000,0,0, 1,np1000,1,1);
	    READ_SDS_ID(sd_id_g,"SolarAzimuth"  ,sola, iline,sp1000,0,0, 1,np1000,1,1);
	    READ_SDS_ID(sd_id_g,"SensorZenith"  ,senz, iline,sp1000,0,0, 1,np1000,1,1);
	    READ_SDS_ID(sd_id_g,"SensorAzimuth" ,sena, iline,sp1000,0,0, 1,np1000,1,1);
	    for (ip=0; ip<np1000; ip++) {
	      hgt1000[idet][ip]  = (float)hgt[ip];
	      solz1000[idet][ip] = (float)solz[ip] * 0.01;
	      sola1000[idet][ip] = (float)sola[ip] * 0.01;
	      senz1000[idet][ip] = (float)senz[ip] * 0.01;
	      sena1000[idet][ip] = (float)sena[ip] * 0.01;
	    }
	  } // if not lonlat
	}

	/* Load data buffers, if required */

	if(!lonlat) {
	    if (resolution < 1000) {
		for (iw=0; iw<nb1000; iw++) {
		    ib = ib1000[iw];
		    for (idet=0; idet<nd1000; idet++) {
			iline = frame * nd1000 + idet;
			READ_SDS_ID(sd_id[2],"EV_1KM_RefSB",&idata[ib*npix], pb1000[iw],iline,sp1000,0,1,1,np1000,1);
			for (ip=0; ip<np1000; ip++)
			    fdatabuf[ib][idet][ip] = (float) idata[ib*npix+ip];
		    }
		}
		for (iw=0; iw<nbir; iw++) {
		    ib = ibir[iw];
		    for (idet=0; idet<nd1000; idet++) {
			iline = frame * nd1000 + idet;
			READ_SDS_ID(sd_id[2],"EV_1KM_Emissive",&idata[ib*npix], pbir[iw],iline,sp1000,0,1,1,np1000,1);
			for (ip=0; ip<np1000; ip++)
			    fdatabuf[ib][idet][ip] = (float) idata[ib*npix+ip];
		    }
		}
		for (iw=0; iw<nbcir; iw++) {
		    ib = ibcir[iw];
		    for (idet=0; idet<nd1000; idet++) {
			iline = frame * nd1000 + idet;
			READ_SDS_ID(sd_id[2],"EV_Band26",&idata[ib*npix], iline,sp1000,0,0,1,np1000,1,1);
			for (ip=0; ip<np1000; ip++)
			    fdatabuf[ib][idet][ip] = (float) idata[ib*npix+ip];
		    }
		}
	    }

	    if (resolution < 500) {
		for (iw=0; iw<nb500; iw++) {
		    ib = ib500[iw];
		    for (idet=0; idet<nd500; idet++) {
			iline = frame * nd500 + idet;
			READ_SDS_ID(sd_id[1],"EV_500_RefSB",&idata[ib*npix], pb500[iw],iline,sp500,0,1,1,np500,1);
			for (ip=0; ip<np500; ip++)
			    fdatabuf[ib][idet][ip] = (float) idata[ib*npix+ip];
			if (destripe) {
			    subframe_calibration(l1rec->sensorID,ib,mrad[ib],brad[ib],sp500,np500,&fdatabuf[ib][idet][0]);
			}
		    }
		}
	    }
	} // if not lonlat

	lastframe = frame;
    }

    *(l1rec->year) = (int32_t)year;
    *(l1rec->day)  = (int32_t)day;
    *(l1rec->msec) = (int32_t)(dsec*1000.0);


    /* Get position and path geometry */

    switch (resolution) {
    case 250:
    case 500:
      for (ip=0; ip<npix; ip++)
	modis_geo_interp(ip,detnum,resolution,
			 &l1rec->lon [ip], &l1rec->lat [ip], &l1rec->height[ip],
			 &l1rec->solz[ip], &l1rec->sola[ip],
			 &l1rec->senz[ip], &l1rec->sena[ip], lonlat);
      break;
    default:
      memcpy(l1rec->lon,   &lon1000 [detnum][0],npix*sizeof(float32));
      memcpy(l1rec->lat,   &lat1000 [detnum][0],npix*sizeof(float32));
      if(!lonlat) {
	memcpy(l1rec->height,&hgt1000 [detnum][0],npix*sizeof(float32));
	memcpy(l1rec->solz,  &solz1000[detnum][0],npix*sizeof(float32));
	memcpy(l1rec->sola,  &sola1000[detnum][0],npix*sizeof(float32));
	memcpy(l1rec->senz,  &senz1000[detnum][0],npix*sizeof(float32));
	memcpy(l1rec->sena,  &sena1000[detnum][0],npix*sizeof(float32));
      } // if not lonlat
      break;
    }

    if(lonlat) {
	return(LIFE_IS_GOOD);
    }


    /* Check for nav errors */

    for (ip=0; ip<npix; ip++) {
	if (l1rec->lon[ip] < -181.0 || l1rec->lon[ip] > 181.0 ||
	    l1rec->lat[ip] <  -91.0 || l1rec->lat[ip] >  91.0 ||
	    badmside)
	  l1rec->navfail[ip] = 1;
    }

    /* Compute polarization frame rotation angles */
    compute_alpha(l1rec->lon, l1rec->lat, l1rec->senz, l1rec->sena,
		  mnorm, npix, l1rec->alpha);


    /* Read L1B VNIR data, scale to radiance, and copy relevant bands to L1 record  */
    /* MODIS format is band sequential.  We want band interlaced.  We use imbedded  */
    /* scale factors to get reflectance, then convert to radiance through mean F0.  */
    /* Note that use of MCST radiance scale factor gives different result.          */

    switch (resolution) {
      case 250:
	for (iw=0; iw<nb250; iw++) {
	    ib = ib250[iw];
	    READ_SDS_ID(sd_id[0],"EV_250_RefSB",&idata[ib*npix], pb250[iw],scan,spix,0,1,1,npix,1);
	    for (ip=0; ip<npix; ip++)
		fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
	    if (destripe) {
		  subframe_calibration(l1rec->sensorID,ib,mrad[ib],brad[ib],spix,npix,&fdata[ib*npix]);
	    }
	}
	for (iw=0; iw<nb500; iw++) {
	    ib = ib500[iw];
	    for (ip=0; ip<npix; ip++) {
		modis_data_interp(ib,ip,detnum,500,250,&fdata[ib*npix+ip]);
		idata[ib*npix+ip] = (uint16) rint(fdata[ib*npix+ip]);
	    }
	}
	for (iw=0; iw<nb1000; iw++) {
	    ib = ib1000[iw];
	    for (ip=0; ip<npix; ip++) {
		modis_data_interp(ib,ip,detnum,1000,250,&fdata[ib*npix+ip]);
		idata[ib*npix+ip] = (uint16) rint(fdata[ib*npix+ip]);
	    }
	}
	for (iw=0; iw<nbir; iw++) {
	    ib = ibir[iw];
	    for (ip=0; ip<npix; ip++) {
		modis_data_interp(ib,ip,detnum,1000,250,&fdata[ib*npix+ip]);
		idata[ib*npix+ip] = (uint16) rint(fdata[ib*npix+ip]);
	    }
	}
	for (iw=0; iw<nbcir; iw++) {
	    ib = ibcir[iw];
	    for (ip=0; ip<npix; ip++) {
		modis_data_interp(ib,ip,detnum,1000,250,&fdata[ib*npix+ip]);
		idata[ib*npix+ip] = (uint16) rint(fdata[ib*npix+ip]);
	    }
	}
	break;

      case 500:
	for (iw=0; iw<nb250; iw++) {
	    ib = ib250[iw];
	    READ_SDS_ID(sd_id[1],"EV_250_Aggr500_RefSB",&idata[ib*npix], pb250[iw],scan,spix,0,1,1,npix,1);
	    for (ip=0; ip<npix; ip++)
		fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
	}
	for (iw=0; iw<nb500; iw++) {
	    ib = ib500[iw];
	    READ_SDS_ID(sd_id[1],"EV_500_RefSB",&idata[ib*npix], pb500[iw],scan,spix,0,1,1,npix,1);
	    for (ip=0; ip<npix; ip++)
		fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
	    if (destripe) {
		  subframe_calibration(l1rec->sensorID,ib,mrad[ib],brad[ib],spix,npix,&fdata[ib*npix]);
	    }
	}
	for (iw=0; iw<nb1000; iw++) {
	    ib = ib1000[iw];
	    for (ip=0; ip<npix; ip++) {
		modis_data_interp(ib,ip,detnum,1000,500,&fdata[ib*npix+ip]);
		idata[ib*npix+ip] = (uint16) rint(fdata[ib*npix+ip]);
	    }
	}
	for (iw=0; iw<nbir; iw++) {
	    ib = ibir[iw];
	    for (ip=0; ip<npix; ip++) {
		modis_data_interp(ib,ip,detnum,1000,500,&fdata[ib*npix+ip]);
		idata[ib*npix+ip] = (uint16) rint(fdata[ib*npix+ip]);
	    }
	}
	for (iw=0; iw<nbcir; iw++) {
	    ib = ibcir[iw];
	    for (ip=0; ip<npix; ip++) {
		modis_data_interp(ib,ip,detnum,1000,500,&fdata[ib*npix+ip]);
		idata[ib*npix+ip] = (uint16) rint(fdata[ib*npix+ip]);
	    }
	}
	break;

      default:
        //  comment the below 20180822
//    for (iw=0; iw<nb250; iw++) {
//        ib = ib250[iw];
//        READ_SDS_ID(sd_id[2],"EV_250_Aggr1km_RefSB",&idata[ib*npix], pb250[iw],scan,spix,0,1,1,npix,1);
//        for (ip=0; ip<npix; ip++)
//        fdata[ib*npix+ip] = (float) idata[ib*npix+ip];

//    }
//    for (iw=0; iw<nb500; iw++) {
//        ib = ib500[iw];
//        READ_SDS_ID(sd_id[2],"EV_500_Aggr1km_RefSB",&idata[ib*npix], pb500[iw],scan,spix,0,1,1,npix,1);
//        for (ip=0; ip<npix; ip++)
//        fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
//    }
//    for (iw=0; iw<nb1000; iw++) {
//        ib = ib1000[iw];
//        READ_SDS_ID(sd_id[2],"EV_1KM_RefSB",&idata[ib*npix], pb1000[iw],scan,spix,0,1,1,npix,1);
//        for (ip=0; ip<npix; ip++)
//        fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
//    }
//    for (iw=0; iw<nbir; iw++) {
//        ib = ibir[iw];
//        READ_SDS_ID(sd_id[2],"EV_1KM_Emissive",&idata[ib*npix], pbir[iw],scan,spix,0,1,1,npix,1);
//        for (ip=0; ip<npix; ip++)
//        fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
//    }
//    for (iw=0; iw<nbcir; iw++) {
//        ib = ibcir[iw];
//        READ_SDS_ID(sd_id[2],"EV_Band26",&idata[ib*npix], scan,spix,0,0, 1,npix,1,1);
//        for (ip=0; ip<npix; ip++)
//        fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
//    }
        for (iw=0; iw<nb250; iw++) {
            ib = ib250[iw];
            READ_SDS_ID(sd_id[2],"EV_250_Aggr1km_RefSB",&idata[ib*npix], pb250[iw],scan,spix,0,1,1,npix,1);
            for (ip=0; ip<npix; ip++)
            fdata[ib*npix+ip] = (float) idata[ib*npix+ip];

        }
        for (iw=0; iw<nb500; iw++) {
            ib = ib500[iw];
            READ_SDS_ID(sd_id[2],"EV_500_Aggr1km_RefSB",&idata[ib*npix], pb500[iw],scan,spix,0,1,1,npix,1);
            for (ip=0; ip<npix; ip++)
            fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
        }
        for (iw=0; iw<nb1000; iw++) {
            ib = ib1000[iw];
            READ_SDS_ID(sd_id[2],"EV_1KM_RefSB",&idata[ib*npix], pb1000[iw],scan,spix,0,1,1,npix,1);
            for (ip=0; ip<npix; ip++)
            fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
        }
        for (iw=0; iw<nbir; iw++) {
            ib = ibir[iw];
            READ_SDS_ID(sd_id[2],"EV_1KM_Emissive",&idata[ib*npix], pbir[iw],scan,spix,0,1,1,npix,1);
            for (ip=0; ip<npix; ip++)
            fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
        }
        for (iw=0; iw<nbcir; iw++) {
            ib = ibcir[iw];
            READ_SDS_ID(sd_id[2],"EV_Band26",&idata[ib*npix], scan,spix,0,0, 1,npix,1,1);
            for (ip=0; ip<npix; ip++)
            fdata[ib*npix+ip] = (float) idata[ib*npix+ip];
        }
    break;
    }

    for (iw=0; iw<nbands; iw++) {

	l1rec->Fo[iw] = Fobar[iw] * fsol;

	for (ip=0; ip<npix; ip++) {

	    ipb = ip*NBANDS+iw;
	    l1rec->Lt[ipb] = BAD_FLT;

	    /* skip night data for visible bands */
	    if (l1rec->solz[ip] >= SOLZNIGHT)
		continue;

	    /* check for sentinel values and flag as appropriate */
	    if (idata[iw*npix+ip] >= 65500) {
		  switch (idata[iw*npix+ip]) {
		  case 65527: /* not in earth view */
		     l1rec->navfail[ip] = 1;
		    break;
                  case 65529: /* saturation */
                  case 65533:
		    l1rec->Lt[ipb] = 1000.0;
		    if (iw <= 12) l1rec->hilt[ip] = 1;
		  default:    /* other stuff */
		    break;
		}

	    } else
		l1rec->Lt[ipb] = (fdata[iw*npix+ip] - b[iw]) * m[iw] * l1rec->Fo[iw]/pi;
	}
    }

    for (iw=nbands; iw<nbands+nbir; iw++) {

	ib = iw-nbands;

	switch (resolution) {
	  case  250: idet=detnum/4; break;
	  case  500: idet=detnum/2; break;
	  case 1000: idet=detnum/1; break;
	}

	for (ip=0; ip<npix; ip++) {

	    ipb = ip*NBANDSIR+ib;
	    l1rec->Ltir[ipb] = 0.0;

	    if (idata[iw*npix+ip] >= 65500) {
		;
	    } else {

		l1rec->Ltir[ipb] = (fdata[iw*npix+ip] - brad[iw]) * mrad[iw]/10.0;


		if (l1rec->sensorID == MODIST || l1rec->sensorID == HMODIST) {
		    l1rec->Ltir[ipb] *= (1.0-radoff[ib][idet]);
		    if (mside == 1) l1rec->Ltir[ipb] *= (1.0 + mfact[ib]);
		}
		if (((file->input->evalmask & SSTMODS) != 0) &&
		    (l1rec->sensorID == MODISA || l1rec->sensorID == HMODISA)) {
		    if (iw == 0 && detnum == 2-1) {
			l1rec->Ltir[ipb] *= ch20d2cor;
		    } else if (iw == 0 && detnum == 3-1) {
			l1rec->Ltir[ipb] *= ch20d3cor;
		    } else if (iw == 0 && detnum == 10-1) {
			l1rec->Ltir[ipb] *= ch20d10cor;
		    } else if (iw == 1 && detnum == 1-1) {
			l1rec->Ltir[ipb] *= ch22d1cor;
		    } else if (iw == 1 && detnum == 8-1) {
			l1rec->Ltir[ipb] *= ch22d8cor;
		    } else if (iw == 1 && detnum == 9-1) {
			l1rec->Ltir[ipb] *= ch22d9cor;
		    } else if (iw == 1 && detnum == 10-1) {
			l1rec->Ltir[ipb] *= ch22d10cor;
		    } else if (iw == 2 && detnum == 1-1) {
			l1rec->Ltir[ipb] *= ch23d1cor;
		    }
		}
	    }
	}
    }

    /* Read cirrus band */

    for (ip=0; ip<npix; ip++) {
	ib = ibcir[0];
	l1rec->rho_cirrus[ip] = 0.0;
	if (idata[iw*npix+ip] < 65500) {
	    l1rec->rho_cirrus[ip] = (fdata[ib*npix+ip] - b_cirrus) * m_cirrus / cos(l1rec->solz[ip]/RADEG);
	 }
    }

    firstScan = 0;

    l1rec->sensorID = file->sensorID;
    l1rec->npix     = file->npix;
    l1rec->detnum   = (int32_t)detnum;
    l1rec->mside    = (int32_t)mside;

    /* Convert IR bands to brightness temperature */
    radiance2bt(l1rec,resolution);

    return(LIFE_IS_GOOD);
}


int closel1_hmodis_hdf(filehandle *file)
{
   int i;

   if ((sd_id_g != sd_id[0]) && SDend(sd_id_g)) {
//      fHY1C_out(stderr,"-E- %s line %d: SDend(%d) failed for file, %s.\n",
//      __FILE__,__LINE__,sd_id[0],file->geofile);
//      return(HDF_FUNCTION_ERROR);
   }
   for (i=0; i<3; i++)
      if (sd_id[i] > 0 && SDend(sd_id[i])) {
//	 fHY1C_out(stderr,"-E- %s line %d: SDend(%d) failed for file, %s.\n",
//	 __FILE__,__LINE__,i,file->name);
//	 return(HDF_FUNCTION_ERROR);
      }

   return(LIFE_IS_GOOD);
}
